#include <event2/event.h>
#include <signal.h>
#include <string.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>
#include <string>
using namespace std;

static string recvstr;
static int recvCount = 0;
static int sendCount = 0;


void c_readcb(bufferevent *be, void *arg)
{
    printf("c_readcb\r\n");
}
void c_writecb(bufferevent *be, void *arg)
{
    printf("c_writecb\r\n");
    FILE *fp = (FILE *)arg;
    char data[1024] = {0};
    memset(data, 0, sizeof(data));
    int len = fread(data, 1, sizeof(data)-1, fp);
    if(len <= 0){
        //读到文件结尾或者出错
        fclose(fp);
        //立刻清理，可能会造成缓冲数据没有发送结束
        //bufferevent_free(be)
        bufferevent_disable(be, EV_WRITE);
        return;
    }
    
    /* 写入buffer */
    if(bufferevent_write(be, data, len)==0);
    {
        printf("----------send len:%d\r\n",len);
        sendCount+=len;
    }
        
    

}
void c_eventcb(bufferevent *be, short what, void *arg)
{
    if(what & BEV_EVENT_TIMEOUT && what & BEV_EVENT_READING){
        printf("BEV_EVENT_READING BEV_EVENT_TIMEOUT\r\n");
        //bufferevent_enable(be, EV_READ);
        bufferevent_free(be);
        return;
    }
    else if(what & BEV_EVENT_ERROR){
        bufferevent_free(be);
        return;
    }
    if(what & BEV_EVENT_CONNECTED){
        printf("BEV_EVENT_CONNECTED\r\n");
        //激活write
        bufferevent_trigger(be,EV_WRITE, 0);
    }
}

/******************************************************/
void read_cb(bufferevent *be, void *arg)
{
    //printf("r\r\n");
    char data[1024] = {0};
    memset(data, 0, sizeof(data));
    printf("start read\r\n");
    int len = bufferevent_read(be, data, sizeof(data)-1);
    if(len<=0){
        printf("len<=0\r\n");
    };
    
    //printf("data:%s\r\n",data);
    if(len>0){
        printf("recv end:%d\r\n",len);
        recvCount+=len;
        recvstr.append(data);
    }

    bufferevent_enable(be,BEV_EVENT_READING);
    
    //bufferevent_write(be, "OK", 2);
}
void write_cb(bufferevent *be, void *arg)
{
    printf("w\r\n");
}
void event_cb(bufferevent *be, short what, void *arg)
{
    if(what & BEV_EVENT_TIMEOUT){
        printf("bev timeout\r\n");

        /*
        char data[1024] = {0};
        memset(data, 0, sizeof(data));
        int len = bufferevent_read(be, data, sizeof(data)-1);
        
        //printf("data:%s\r\n",data);
        while(len>0){
            printf("last recv end:%d\r\n",len);
            recvCount+=len;
            recvstr.append(data);
            memset(data, 0, sizeof(data));
            len = bufferevent_read(be, data, sizeof(data)-1);
        }
        */

        printf("recvstr size:%d\r\n%s\r\n",recvstr.size(),recvstr.c_str());

        //bufferevent_enable(be, EV_READ);
        printf("*******\r\nrecvCount:%d-sendCount:%d\r\n", recvCount,sendCount);
        bufferevent_free(be);
    }
    else {
        printf("other event\r\n");
    }
}
/******************************************************/
void listen_cb(evconnlistener *ev, evutil_socket_t fd, sockaddr *sin, int slen, void *arg)
{
    printf("create fd for a client:%d\r\n", fd);

    event_base *base = (event_base*)arg;

    bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);

    //添加监控事件
    bufferevent_enable(bev, EV_READ|EV_WRITE);

    //水位
    bufferevent_setwatermark(bev, EV_READ, 0, 0);
    bufferevent_setwatermark(bev, EV_WRITE, 5, 0);

    timeval t1 = {10, 0};
    bufferevent_set_timeouts(bev, &t1, 0);

    //设置回调函数
    bufferevent_setcb(bev, read_cb, write_cb, event_cb, 0);

}
/* 
*
*   main
*
*/
int main()
{
    if(signal(SIGPIPE, SIG_IGN) == SIG_ERR)
        return 1;

    event_base *base = event_base_new();

    /* create server */
    sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(9006);

    evconnlistener *ev = evconnlistener_new_bind(
        base,
        listen_cb,
        base,
        LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
        10,
        (sockaddr*)&sin,
        sizeof(sin)
    );

    if(ev==NULL){
        perror("error\r\n");
    }
    evutil_socket_t listenfd = evconnlistener_get_fd(ev);
    printf("listener fd:%d\r\n",listenfd);

    //* client
    bufferevent *bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
    sockaddr_in csin;
    memset(&csin, 0, sizeof(csin));
    csin.sin_family = AF_INET;
    csin.sin_port = htons(9006);
    evutil_inet_pton(AF_INET,"127.0.0.1",&csin.sin_addr.s_addr);

    FILE *fp = fopen("test_buffer_client.cpp", "rb");
    bufferevent_setcb(bev, c_readcb, c_writecb, c_eventcb, fp);
    bufferevent_enable(bev, EV_READ|EV_WRITE);
    int re = bufferevent_socket_connect(bev, (sockaddr*)&csin, sizeof(csin));
    if(re==0){
        printf("connect to server success\r\n");
    }
    

    /* loop */
    event_base_dispatch(base);
    
    evconnlistener_free(ev);
    /* free */
    event_base_free(base);

    return 1;
}